<?php

namespace command;

use app\admin\model\AdminModel;
use app\admin\model\AdminPermissionModel;
use app\admin\model\ConfigModel;
use app\admin\model\LogErrorModel;
use app\admin\model\seed\AdminPermissionSeed;
use app\admin\model\seed\AdminSeed;
use app\admin\model\seed\ConfigSeed;
use Exception;
use exception\FriendlyException;
use thinkless\common\BaseCommand;
use util\Migration;
use think\console\input\Option;
use think\facade\Config;

/**
 * php think install -p qweqwe123 -f
 */
class Install extends BaseCommand
{
    protected $database = '';
    protected $hostname = '';
    protected $hostport = '';
    protected $username = '';
    protected $password = '';

    protected $force = false;
    protected $noTipForce = false;

    protected $installTable = '';

    /**
     * @var Migration
     */
    protected $migration = null;

    private $installTables = [
        AdminModel::class,
        AdminPermissionModel::class,
        LogErrorModel::class,
        ConfigModel::class,
    ];

    private $seeds = [
        AdminSeed::class,
        AdminPermissionSeed::class,
        ConfigSeed::class,
    ];

    protected function configure() {
        $config = Config::get('database');
        $defaultConfig = $config['connections']['mysql'];
        $this->setName('install')
            ->addOption('hostname', 'H', Option::VALUE_OPTIONAL, 'mysql hostname', $defaultConfig['hostname'])
            ->addOption('hostport', 'P', Option::VALUE_OPTIONAL, 'mysql hostport', $defaultConfig['hostport'])
            ->addOption('database', 'db', Option::VALUE_OPTIONAL, 'mysql database', $defaultConfig['database'])
            ->addOption('username', 'u', Option::VALUE_OPTIONAL, 'mysql username', $defaultConfig['username'])
            ->addOption('password', 'p', Option::VALUE_OPTIONAL, 'mysql password', $defaultConfig['password'])
            ->addOption('table', 't', Option::VALUE_OPTIONAL, 'table only', null)
            ->addOption('force', 'f', Option::VALUE_NONE, 'force override', null)
            ->addOption('notipforce', 'F', Option::VALUE_NONE, 'no tip force override', null)
            ->setDescription('Thinkless数据库初始化');
    }

    /**
     * 命令行安装
     */
    protected function start() {
        $this->hostname = $this->input->getOption('hostname');
        $this->hostport = $this->input->getOption('hostport');
        $this->username = $this->input->getOption('username');
        $this->password = $this->input->getOption('password');
        $this->database = $this->input->getOption('database');
        $this->installTable = $this->input->getOption('table');
        $this->force = $this->input->hasOption('force');
        $this->noTipForce = $this->input->hasOption('notipforce');
        if($this->noTipForce) $this->force = true;
        $this->checkenv();
        $this->initConnect();
        $this->checkDatabase();
        $this->install();
        $this->info("安装成功!");
    }

    protected function checkenv() {
        if (version_compare(PHP_VERSION, '7.2.0', '<')) {
            throw new Exception("PHP版本过低");
        }
        return true;
    }

    private function initConnect() {
        $this->info("Mysql数据库配置:");
        $this->info(" - hostname:".$this->hostname);
        $this->info(" - hostport:".$this->hostport);
        $this->info(" - database:".$this->database);
        $this->info(" - username:".$this->username);
        $this->info(" - password:".$this->password);
        if($this->installTable) $this->info("安装表: ". $this->installTable);
        if(!$this->noTipForce && !$this->readYN('请确认数据库配置', true)) throw new Exception("取消过程");
        // 第一次创建没数据库
        $this->initMigration('mysql');
    }

    private function initMigration($database) {
        $this->migration = Migration::build([
            'hostname'        => $this->hostname,
            'hostport'        => $this->hostport,
            'username'        => $this->username,
            'password'        => $this->password,
            'database'        => $database,
        ]);
    }

    private function checkDatabase() {
        $this->info("检查数据库:");
        // 只安装某个表
        if(!empty($this->installTable)) {
            if(!$this->migration->hasDatabase($this->database)) throw new Exception("需要先创建数据库");
            if($this->migration->hasTable($this->installTable)) {
                if(!$this->force) throw new FriendlyException("已有数据表");
                if(!$this->readYN('是否确认覆盖数据表')) throw new Exception("取消过程");
            } 
            $this->initMigration($this->database);
            return;
        }
        if($this->migration->hasDatabase($this->database)) {
            if(!$this->force) throw new Exception("已有同名数据库: ". $this->database);
            if(!$this->readYN('是否确认覆盖数据库')) throw new Exception("取消过程");
            $this->migration->dropDatabase($this->database);
            $this->output->info("删除数据库【{$this->database}】成功!");
        }
        $this->migration->createDatabase($this->database);
        $this->output->info("创建数据库【{$this->database}】成功!");
        $this->initMigration($this->database);
    }

    protected function install() {
        $this->output->info("创建数据表:");
        foreach ($this->installTables as $class) {
            $table = $this->migration->getTableInfo($class);
            if($this->installTable && $table['name'] != $this->installTable) continue;
            $this->output->info(" - 【".$table['name']."】: 创建中");
            $this->migration->recreateTable($table);
            $this->output->info(" - 【".$table['name']."】: 创建成功");
        }
        $this->output->info("导入数据:");
        foreach ($this->seeds as $seedClass) {
            $seed = (new $seedClass);
            $table = $this->migration->getTableInfo($seed->getClass());
            if($this->installTable && $table['name'] != $this->installTable) continue;
            $this->output->info(" - 【".$table['name']."】: 导入中");
            $data = $seed->seed('install');
            $this->migration->seed($table, $data);
        }
        $this->migration->dropSchemaTable();
    }
}
